package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLog;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLogConstant;
import com.cskaoyan.wordmemorize.common.entity.BaseDO;
import com.cskaoyan.wordmemorize.converter.RolePermissionConverter;
import com.cskaoyan.wordmemorize.dao.entity.PermissionDO;
import com.cskaoyan.wordmemorize.dao.entity.RoleDO;
import com.cskaoyan.wordmemorize.dao.entity.RolePermissionDO;
import com.cskaoyan.wordmemorize.dao.mapper.PermissionMapper;
import com.cskaoyan.wordmemorize.dao.mapper.RoleMapper;
import com.cskaoyan.wordmemorize.dao.mapper.RolePermissionMapper;
import com.cskaoyan.wordmemorize.dto.admin.*;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.PermissionCommand;
import com.cskaoyan.wordmemorize.request.RoleCommand;
import com.cskaoyan.wordmemorize.request.RolePermissionCommand;
import com.cskaoyan.wordmemorize.service.RolePermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class RolePermissionServiceImpl implements RolePermissionService {
    @Autowired
    RoleMapper roleMapper;

    @Autowired
    RolePermissionConverter rolePermissionConverter;
    @Autowired
    PermissionMapper permissionMapper;
    @Autowired
    RolePermissionMapper rolePermissionMapper;


    // todo:获取账号权限列表（返回权限树）
    @Override
    public List<PermissionDTO> getPermissions() {
        // todo:获取所有根节点
        LambdaQueryWrapper<PermissionDO> permissionQueryWrapper = new LambdaQueryWrapper<>();
        permissionQueryWrapper.eq(PermissionDO::getParentPermission, -1);
        List<PermissionDO> permissionDOs = permissionMapper.selectList(permissionQueryWrapper);
        List<PermissionDTO> permissionDTOs = rolePermissionConverter.employeePermissionDO2DTO(permissionDOs);
        // todo:清空查询条件构造器（QueryWrapper 或 LambdaQueryWrapper）中所有已设置条件
        permissionQueryWrapper.clear();
        // todo:获取每个根节点的子权限
        permissionDTOs.forEach(permissionDTO -> {
            getOnePermission(permissionDTO);
        });
        return permissionDTOs;
    }

    // todo:Tcc增加---权限树用的工具方法，递归获取一个节点及该节点下的所有子节点
    public void getOnePermission(PermissionDTO permissionDTO) {
        LambdaQueryWrapper<PermissionDO> permissionQueryWrapper = new LambdaQueryWrapper<>();
        permissionQueryWrapper.eq(PermissionDO::getParentPermission, Long.valueOf(permissionDTO.getId()));
        List<PermissionDO> childrenPermissionDOs = permissionMapper.selectList(permissionQueryWrapper);
        // todo:若当前传入节点无子节点，则返回
        if (CollectionUtils.isEmpty(childrenPermissionDOs)) {
            permissionDTO.setChildren(null);
            return;
        }
        // todo:当前传入节点有子节点，则递归
        List<PermissionDTO> childrenPermissionDTOs = rolePermissionConverter.employeePermissionDO2DTO(childrenPermissionDOs);
        childrenPermissionDTOs.forEach(this::getOnePermission);
        // todo:此时子节点的所有子节点全部设置完毕，可以将子节点设置给当前节点
        permissionDTO.setChildren(childrenPermissionDTOs);
    }


    // todo:获取账号角色列表（包含不分页，无条件分页查询，有条件分页查询）
    @Override
    public PageDTO<RoleDTO> getRoleList(PageRequest pageRequest) {
        if (pageRequest.getPageNum() == null) {
            List<RoleDO> roleDOs = roleMapper.selectList(null);
            return rolePermissionConverter.roleList2Page(roleDOs, (long) roleDOs.size());
        }
        Page<RoleDO> pageParam = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());
        LambdaQueryWrapper<RoleDO> roleQueryWrapper = new LambdaQueryWrapper<>();
        // todo:判断是否有条件
        if (pageRequest.getKeyword() != null) {
            roleQueryWrapper.like(RoleDO::getName, pageRequest.getKeyword());
        }
        Page<RoleDO> rolePage = roleMapper.selectPage(pageParam, roleQueryWrapper);
        return rolePermissionConverter.roleList2Page(rolePage.getRecords(), rolePage.getTotal());
    }

    @OperateLog(dataType = "角色", operateType = OperateLogConstant.OPERATE_ADD)
    @Override
    public void addRole(RoleCommand command) {
        RoleDO roleDO = rolePermissionConverter.command2RoleDO(command);
        roleMapper.insert(roleDO);
    }

    @OperateLog(dataType = "角色", operateType = OperateLogConstant.OPERATE_UPDATE)
    @Override
    public void updateRole(RoleCommand roleCommand) {
        RoleDO roleDO = rolePermissionConverter.command2RoleDO(roleCommand);
        roleMapper.updateById(roleDO);
    }

    // todo:账号角色授权
    @OperateLog(dataType = "角色权限", operateType = OperateLogConstant.OPERATE_UPDATE)
    @Override
    public void updateRolePermission(RolePermissionCommand command) {
        Long roleId = Long.valueOf(command.getRoleId());
        // todo:获取前端传递的权限集合
        List<Long> permissions = command.getPermissions().stream().map(Long::valueOf).collect(Collectors.toList());
        // todo:获取数据库中该roleId的权限集合
        LambdaQueryWrapper<RolePermissionDO> rolePermissionQueryWrapper = new LambdaQueryWrapper<>();
        rolePermissionQueryWrapper.eq(RolePermissionDO::getRoleId, roleId);
        List<RolePermissionDO> rolePermissionDOs = rolePermissionMapper.selectList(rolePermissionQueryWrapper);
        List<Long> databasePermissions = rolePermissionDOs.stream().map(RolePermissionDO::getPermissionId).collect(Collectors.toList());
        // todo:将数据库中角色的权限和前端传递角色权限集合作比较找出数据库中用户还未绑定的权限
        List<Long> notBoundPermissions = permissions.stream().filter(permission -> !databasePermissions.contains(permission)).collect(Collectors.toList());
        List<RolePermissionDO> notBoundRolePermissionDOs = new ArrayList<>();
        // todo:将List<Long>转换为对应的List<RolePermissionDO>，批量插入
        notBoundPermissions.forEach(notBoundPermission -> {
            RolePermissionDO rolePermissionDO = new RolePermissionDO();
            rolePermissionDO.setRoleId(roleId);
            rolePermissionDO.setPermissionId(notBoundPermission);
            notBoundRolePermissionDOs.add(rolePermissionDO);
        });
        rolePermissionMapper.insert(notBoundRolePermissionDOs);
    }

    // todo:获取角色对应的授权信息(权限树)
    @Override
    public RolePermissionDTO getRolePermissionList(Long roleId) {
        RolePermissionDTO rolePermissionDTO = new RolePermissionDTO();
        rolePermissionDTO.setSystemPermissions(this.getPermissions());
        LambdaQueryWrapper<RolePermissionDO> rolePermissionQueryWrapper = new LambdaQueryWrapper<>();
        rolePermissionQueryWrapper.eq(RolePermissionDO::getRoleId, roleId);
        List<RolePermissionDO> rolePermissionDOs = rolePermissionMapper.selectList(rolePermissionQueryWrapper);

        // todo:若用户无权限，直接返回
        if (CollectionUtils.isEmpty(rolePermissionDOs)) {
            rolePermissionDTO.setAssignedPermissions(null);
            return rolePermissionDTO;
        }

        List<Long> roleAllPermissions = rolePermissionDOs.stream().map(RolePermissionDO::getPermissionId).collect(Collectors.toList());

        // todo:将角色已授权的权限中类型为1的去掉，仅保留权限类型为2的
        LambdaQueryWrapper<PermissionDO> permissionQueryWrapper = new LambdaQueryWrapper<>();
        permissionQueryWrapper.in(PermissionDO::getId, roleAllPermissions)
                .eq(PermissionDO::getPermissionType, 2);
        // todo:把List<Long>转换为List<String>
        List<PermissionDO> permissionDOS = permissionMapper.selectList(permissionQueryWrapper);
        List<String> assignedPermissions = null;
        if (!CollectionUtils.isEmpty(permissionDOS)) {
            assignedPermissions = permissionDOS.stream().map(permissionDO -> permissionDO.getId().toString()).collect(Collectors.toList());
        }
        rolePermissionDTO.setAssignedPermissions(assignedPermissions);
        return rolePermissionDTO;
    }

    // todo；删除账号角色
    @OperateLog(dataType = "角色", operateType = OperateLogConstant.OPERATE_SINGLE_DELETE)
    @Override
    public DeleteRoleOperateDTO deleteRole(Long roleId) {
        RoleDO roleDO = roleMapper.selectById(roleId);
        roleMapper.deleteById(roleId);
        return rolePermissionConverter.toDeleteRoleOperateDTO(roleDO);
    }

    // todo:在给角色授权时，删除指定角色绑定的指定权限
    @OperateLog(dataType = "角色权限", operateType = OperateLogConstant.OPERATE_BATCH_DELETE)
    @Override
    public DeleteRolePermissionOperateDTO deleteRolePermission(Long roleId, Long permissionId) {
        // todo:获取要删除的所有权限(包括其子权限)
        List<Long> list = new ArrayList<>();
        getAllPermissionId(permissionId, list);
        System.out.println("list = " + list);
        LambdaQueryWrapper<RolePermissionDO> rolePermissionQueryWrapper = new LambdaQueryWrapper<>();
        rolePermissionQueryWrapper.eq(RolePermissionDO::getRoleId, roleId)
                .in(RolePermissionDO::getPermissionId, list);
        rolePermissionMapper.delete(rolePermissionQueryWrapper);
        // todo:返回值给查询日志用，前端不需要
        RoleDO roleDO = roleMapper.selectById(roleId);
        PermissionDO permissionDO = permissionMapper.selectById(permissionId);
        return rolePermissionConverter.toDeleteRolePermissionOperateDTO(roleDO, permissionDO);
    }


    // todo---------------邵 补充三个API

    // todo 添加账号权限--保存权限树(后台账号权限管理-权限管理)
    @Override
    public void savePermissions(PermissionCommand command) {

        // 把字符串转化成DO对象，并存进数据库
        PermissionDO permissionDO = rolePermissionConverter.command2PermissionDO(command);
        permissionMapper.insert(permissionDO);
    }


    // todo 修改账号权限--更新权限树(后台账号权限管理-权限管理)
    @Override
    public void updatePermission(PermissionCommand command) {

        // 把字符串转化成DO对象，并覆盖进数据库
        PermissionDO permissionDO = rolePermissionConverter.command2PermissionDO(command);
        permissionMapper.updateById(permissionDO);
    }


    // todo 删除指定账号权限--删除指定权限(后台账号权限管理-权限管理)
    @Override
    public DeletePermissionOperateDTO deletePermission(Long permissionId) {

        // todo:获取当前要删除的权限及其所有子权限
        List<Long> list = new ArrayList<>();
        getAllPermissionId(permissionId, list);

        // todo:删除获取的所有权限
        LambdaQueryWrapper<PermissionDO> permissionQueryWrapper = new LambdaQueryWrapper<>();
        permissionQueryWrapper.in(PermissionDO::getId, list);
        permissionMapper.delete(permissionQueryWrapper);

        PermissionDO permissionDO = permissionMapper.selectById(permissionId);
        return rolePermissionConverter.toDeletePermissionOperateDTO(permissionDO);
    }

    // todo:Tcc增加-将传入权限及其所有子权限,存入传进的List<Long>中
    public void getAllPermissionId(Long permissionId, List<Long> list) {
        list.add(permissionId);
        LambdaQueryWrapper<PermissionDO> permissionQueryWrapper = new LambdaQueryWrapper<>();
        permissionQueryWrapper.eq(PermissionDO::getParentPermission, permissionId);
        List<PermissionDO> permissionDOs = permissionMapper.selectList(permissionQueryWrapper);
        // todo:若传入权限无子权限，返回
        if (CollectionUtils.isEmpty(permissionDOs)) {
            return;
        }
        // todo:若传入权限有子权限，查询并加入Id
        List<Long> permissionList = permissionDOs.stream().map(permissionDO -> {
            Long tempPermissionId = permissionDO.getId();
            getAllPermissionId(tempPermissionId, list);
            return tempPermissionId;
        }).collect(Collectors.toList());
        list.addAll(permissionList);
    }

}
